package nj.yb.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ClientBootStrap {


    private Scanner scanner = new Scanner(System.in);
    //创建唯一的ChatClientHandler实例
    private final ChatClientHandler chatClientHandler = new ChatClientHandler();
    //用 volatile 标记控制聊天线程的停止（替代关闭通道）
    volatile boolean isChatExit = false;

    static boolean isFirstHistory = true;


    public void run(){
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            // 2. 管道中添加全局唯一的handler实例
                            ch.pipeline().addLast(chatClientHandler);
                        }
                    })
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 1. 第一步：添加按行分割解码器（解决断包/粘包，关键！）
                            // 参数 1024*1024 是最大帧长度（1MB，足够容纳50条历史消息的JSON）
                            ch.pipeline().addLast(new io.netty.handler.codec.LineBasedFrameDecoder(1024 * 1024));

                            // 2. 第二步：再添加原有的字符串解码器和编码器
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());

                            // 3. 第三步：添加全局唯一的 handler 实例（原代码保留）
                            ch.pipeline().addLast(chatClientHandler);
                        }
                    })
            ;
            //ChannelFuture future = bootstrap.connect("81871ef6ol50.vicp.fun:",35030).sync();
            ChannelFuture future = bootstrap.connect("localhost",8081).sync();
            Channel channel = future.channel();
            System.out.println("连接服务器成功！欢迎进入聊天系统。。。");

            // 3. 只创建一次ChatClient实例，避免重复创建
            ChatClient client = new ChatClient(chatClientHandler);

            while(true){
                int choice = Integer.MAX_VALUE;
                while(true){
                    int flag = 0;
                    System.out.println("===============菜单=================");
                    System.out.println("0、退出");
                    System.out.println("1、注册");
                    System.out.println("2、登陆");
                    System.out.print("请输入：");
                    String choiceStr = scanner.next();
                    try {
                        choice = Integer.parseInt(choiceStr);
                    }catch (Exception e){
                        flag = 1;
                        System.out.println("输入错误，请输入数字！");
                    }

                    if(flag == 0){
                        break;
                    }
                }

                switch (choice){
                    case 0:
                        if (channel.isActive()) {
                            channel.close().sync();
                        }
                        System.out.println("已退出系统");
                        return;
                    case 1:
                        client.sendRegisterRequest(channel);
                        break;
                    case 2:
                        boolean isLogin = client.sendLoginRequest(channel);
                        if(isLogin){
                            showMenuAndDo(channel,client);
                        }
                        break;
                }

            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            group.shutdownGracefully();
        }
    }

    private void showMenuAndDo(Channel channel,ChatClient client) throws InterruptedException {
        while (true){
            int choice = Integer.MAX_VALUE;
            while(true){
                int flag = 0;
                System.out.println("===============菜单=================");
                System.out.println("0、退出登录");
                System.out.println("1、获取好友列表");
                System.out.println("2、获取群聊列表");
                //TODO
                System.out.println("3、获取历史聊天记录");
                System.out.println("4、添加好友");
                System.out.println("5、加入群聊");
                System.out.println("6、创建新的群聊");
                System.out.println("7、私聊");
                System.out.print("请选择：");
                String choiceStr = scanner.next();
                try {
                    choice = Integer.parseInt(choiceStr);
                }catch (Exception e){
                    flag = 1;
                    System.out.println("输入错误，请输入数字！");
                }

                if(flag == 0){
                    break;
                }
            }

            switch (choice){
                case 0:
                    System.out.println("已退出登录，返回主菜单");
                    return;
                case 1:
                    CountDownLatch friendLatch = new CountDownLatch(1);
                    chatClientHandler.setFriendListLatch(friendLatch);
                    client.sendFriendListRequest(channel);

                    boolean friendIsTimeOut = !friendLatch.await(10, TimeUnit.SECONDS);
                    if(friendIsTimeOut){
                        System.out.println("获取好友列表超时，请稍候再试！");
                    }
                    break;
                case 2:
                    CountDownLatch groupListLatch = new CountDownLatch(1);
                    chatClientHandler.setGroupListLatch(groupListLatch);
                    client.sendGetGroupListRequest(channel);
                    boolean groupsIsTimeOut = !groupListLatch.await(10, TimeUnit.SECONDS);
                    if(groupsIsTimeOut){
                        System.out.println("获取群聊列表超时，请稍候再试！");
                    }
                    break;
                case 3:
                    CountDownLatch historyLatch = new CountDownLatch(1);
                    chatClientHandler.setHistoryMessageLatch(historyLatch);
                    client.sendHistoryRequest(channel);
                    long timeout = isFirstHistory ? 15 : 10;
                    boolean historyIsTimeOut = !historyLatch.await(timeout,TimeUnit.SECONDS);
                    if(historyIsTimeOut){
                        System.out.println("获取历史消息超时，请稍候再试！！！");
                        if(isFirstHistory){
                            System.out.println("正在重试。。。");
                            historyLatch = new CountDownLatch(1);
                            chatClientHandler.setHistoryMessageLatch(historyLatch);
                            client.sendHistoryRequest(channel); // 重新发送请求
                            historyIsTimeOut = !historyLatch.await(10, TimeUnit.SECONDS);
                            if (historyIsTimeOut) {
                                System.out.println("重试失败，请稍后再试");
                            } else {
                                isFirstHistory = false; // 重试成功后标记为非首次
                            }
                        }
                    }else {
                        // 首次成功后标记为非首次
                        isFirstHistory = false;
                    }
                    break;
                case 4:
                    CountDownLatch addFriendLatch = new CountDownLatch(1);
                    chatClientHandler.setAddFriendLatch(addFriendLatch);
                    client.sendAddFriendRequest(channel);

                    boolean addFriendIsTimeOut = !addFriendLatch.await(10, TimeUnit.SECONDS);
                    if(addFriendIsTimeOut){
                        System.out.println("添加好友超时，请稍候再试！");
                    }
                    break;
                case 5:
                    //加入群聊

                    break;
                case 6:
                    //创建新的群聊

                    break;
                case 7:
                    isChatExit = false;
                    privateChat(channel,client);
                    break;
            }

        }
    }



    private void privateChat(Channel channel, ChatClient client) throws InterruptedException {
        System.out.println("开始聊天！输入exit退出当前聊天");
        System.out.print("请输入要聊天的用户名：");
        String targetUsername = scanner.next();
        scanner.nextLine(); // 消费换行符，避免后续输入异常

        client.sendNotReadMessagesRequest(channel,targetUsername);

        // 聊天发送线程
        Thread sendThread = new Thread(() -> {
            while (!isChatExit) { // 线程循环条件：未退出聊天
                try {
                    // 2. 检查线程是否被中断（避免阻塞时无法退出）
                    if (Thread.currentThread().isInterrupted()) {
                        break;
                    }

                    String input = scanner.nextLine().trim();
                    if (input.isEmpty()) continue;

                    if ("exit".equals(input)) {
                        isChatExit = true; // 标记退出聊天
                        System.out.println("已退出当前聊天，返回功能菜单");
                        break;
                    }

                    // 通道正常时才发送消息（避免通道已关闭的异常）
                    if (channel.isActive()) {
                        client.sendChatRequest(channel, input, targetUsername);
                    } else {
                        isChatExit = true;
                        System.out.println("通道已关闭，无法发送消息");
                        break;
                    }
                } catch (Exception e) {
                    isChatExit = true;
                    System.out.println("聊天异常，退出当前聊天：" + e.getMessage());
                    break;
                }
            }
        });
        sendThread.start();

        // 3. 等待聊天线程结束（不阻塞主线程）
        sendThread.join();
    }



    public static void main(String[] args) {
        new ClientBootStrap().run();
    }
}
